﻿#pragma once
#include <string>
#include <list>
#include <queue>
#include <memory>
#include <mutex>
#include <unordered_map>
using namespace std;
class c_session_webs;
typedef std::shared_ptr<c_session_webs> ptr_session_webs;
typedef struct s_memory_flv
{
	uint8_t *v_data_h;
	uint8_t *v_data = NULL;
	size_t   v_len;
	uint32_t v_ts; // timestamp
	//std::atomic_compare_exchange_strong()


#define PADDING 18
	void memory_create(uint32_t len)
	{
		//预留18字节，兼容rtmp协议，最多18字节
		//兼容websocket协议，       最多10字节
		//flv 结尾4字节
		v_data_h = new uint8_t[len+ PADDING];
		v_data = v_data_h + PADDING;
		v_len = len; //not include the header and tail 
	}
	~s_memory_flv()
	{
		if (v_data_h != NULL)
			delete[] v_data_h;
	}
}s_memory_flv;
typedef std::shared_ptr<s_memory_flv> ptr_s_memory;
typedef std::queue<ptr_s_memory> t_queue_data;
#define USE_LIST 1

typedef struct s_hub
{
#if USE_LIST
	using t_list_w = std::list<ptr_session_webs>;
	//using t_list_h = std::list<ptr_session_http>;
#else
	using t_list = std::unordered_set<ptr_ws_session>;
#endif
	uint8_t flvhead[13];
	t_list_w v_list_webs;
	t_list_w v_list_http;
	t_queue_data v_queue;
	ptr_s_memory v_meta;
	//header of video 
	ptr_s_memory v_cache_headerv;
	//header of audio
	ptr_s_memory v_cache_headera;
	int v_need_audio = 0;
	int v_need_video = 0;
	//Is the coroutine started
	int v_coroutine_start = 0;
	//上一次的数据长度
	uint32_t v_last_prev_tag_len = 0;
}s_flvhub;

class c_flvhubs
{
	static std::once_flag v_oc;//just call_once
	static c_flvhubs *v_inst;
public:

	static c_flvhubs *instance() {
		std::call_once(v_oc, [&]
		{
			v_inst = new c_flvhubs();
		});
		return v_inst;
	}
private:
	std::unordered_map<uint32_t, s_flvhub> v_session_ptrs;
	c_flvhubs() {}
	~c_flvhubs() {}
public:
	s_flvhub & get(uint32_t key)
	{
		return v_session_ptrs[key];
	}
	s_flvhub *push_session(uint32_t key, ptr_session_webs val,bool ishttp = false)
	{
		if(v_session_ptrs.find(key) == v_session_ptrs.end())
			return NULL;
		s_flvhub &list = v_session_ptrs[key];
		if (!ishttp)
			list.v_list_webs.push_back(val);
		else
			list.v_list_http.push_back(val);
		return &list;
	}
	
	//8 is audio
	//9 is video
	int push_data(uint32_t key, ptr_s_memory mem)
	{
		s_flvhub &list = v_session_ptrs[key];
		list.v_queue.push(mem);
		return 0;
	}
};

